package com.xbongbong.pro.dataset.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.xbongbong.paas.bi.pojo.DataSetValueAnalysisPojo;
import com.xbongbong.paas.bi.pojo.dto.DataSetParseDTO;
import com.xbongbong.paas.bi.pojo.vo.DataSetResultVO;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.XbbConstant;
import com.xbongbong.paas.enums.BIProductReformEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.bi.DataSetFieldStatusEnum;
import com.xbongbong.paas.enums.bi.DataSetNodeTypeEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.dataset.helper.RelatedProductHelper;
import com.xbongbong.pro.dataset.service.DataSetPreViewResultService;
import com.xbongbong.pro.dataset.service.ParseSqlService;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.domain.entity.DataSetEntity;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.BiErrorCodeEnum;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.help.ChartResultHelp;
import com.xbongbong.pro.statistic.help.DataSetHelp;
import com.xbongbong.pro.statistic.pojo.ChartFieldAttrPojo;
import com.xbongbong.pro.statistic.result.pojo.FieldAttrPojo;
import com.xbongbong.pro.statistics.help.CommonHelper;
import com.xbongbong.pro.statistics.help.DisplayHelper;
import com.xbongbong.pro.statistics.service.StarDataService;
import com.xbongbong.pro.statistics.strategy.chart.type.impl.DataQueryTableStrategyServiceImpl;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.SelectProductEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;


@Service("dataSetPreViewResultService")
public class DataSetPreViewResultServiceImpl implements DataSetPreViewResultService {
    @Resource
    private StarDataService starDataService;
    @Resource
    private ParseSqlService parseSqlSerive;
    @Resource
    private ChartResultHelp chartResultHelp;
    @Resource
    private DisplayHelper displayHelper;
    @Resource
    private DataQueryTableStrategyServiceImpl dataQueryTableStrategyServiceImpl;
    @Resource
    private DataSetHelp dataSetHelp;
    @Resource
    private RelatedProductHelper relatedProductHelper;
    @Resource
    private CommonHelper commonHelper;

    public Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    public DataSetResultVO getResult(DataSetParseDTO dataSetParseDTO) throws XbbException {
        DataSetResultVO dataSetResultVO = parseSqlSerive.parseSql(dataSetParseDTO);
        String parseSql = dataSetResultVO.getParseSql();
        if (commonHelper.getPrintLog(dataSetParseDTO.getCorpid())) {
            //  数据集id    dataSetId 可能为null
            logger.info("DS===preview===dataSetId===" + dataSetParseDTO.getDataSetId() + "===SQL===" + parseSql);
        }
        if (StringUtil.isEmpty(parseSql)) {
            logger.error("parseSql is empty");
            throw new XbbException(BiErrorCodeEnum.API_ERROR_241034);
        }
        List resultList = null;
        try {
            resultList = starDataService.findListMapBySql(parseSql);
        } catch (Exception e) {
            logger.error("",e);
            throw new XbbException(BiErrorCodeEnum.API_ERROR_241034);
        }
        JSONObject boardJson = dataSetParseDTO.getJsonStr();
        //找到最后一个节点(除去输出节点的最后一个)
        String nodeId = null;
        Map<Long, DataSetValueAnalysisPojo> formIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //处理关联产品
        Set<String>  inputNodeIdSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<String>  inputIdSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, String> formIdNodeIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<String> boardKeySet = boardJson.keySet();
        if(dataSetParseDTO.isPreView() && XbbConstant.REQ_SOURCE_BOARD.equals(dataSetParseDTO.getReqSource())){
            Set<String>  nodeIdSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (String s : boardKeySet) {
                JSONObject json = boardJson.getJSONObject(s);
                //输入节点不会是最后一个节点
                if(Objects.equals(json.getString(XbbConstant.TYPE), DataSetNodeTypeEnum.INPUT.getAlias())){
                    inputNodeIdSet.add(s);
                    nodeIdSet.add(s);
                    //TODO 收集所有的formId查出explain，组建待使用map
                    Long formId = json.getLong(StringConstant.FORM_ID);
                    //关联产品特殊处理
                    if (BIProductReformEnum.getProductSubBusList().contains(json.getInteger(StringConstant.BUSINESS_TYPE))){
                        formIdNodeIdMap.put(formId,s);
                    }
                    JSONArray jsonJSONArray = json.getJSONArray(XbbConstant.DS_FIELD);
                    if (Objects.nonNull(jsonJSONArray)){
                        formIdMap.put(formId,new DataSetValueAnalysisPojo(json.getInteger(StringConstant.BUSINESS_TYPE),JSONArray.parseArray(jsonJSONArray.toJSONString(), ChartFieldAttrPojo.class)));
                    }
                }else if(Objects.equals(json.getString(XbbConstant.TYPE), DataSetNodeTypeEnum.OUTPUT.getAlias())){
                    //输出节点直接去找他的input
                }else {
                    //非输出节点是最后一个节点，是预览
                    nodeIdSet.add(s);
                    //当前节点的输入
                    inputIdSet.addAll(json.getJSONArray(DataSetNodeTypeEnum.INPUT.getAlias()).stream().map(Object::toString).collect(Collectors.toSet()));
                }
            }
            //留下需要终端节点（类似输出节点）
            nodeIdSet.removeAll(inputIdSet);
            if(!Objects.equals(nodeIdSet.size(),1)){
                //设计有误或者有东西没传来
                throw  new XbbException(ErrorCodeEnum.API_ERROR_263003);
            }
            for (String s : nodeIdSet) {
                nodeId = s;
                break;
            }
        }else {
            for (String node : boardKeySet) {
                JSONObject json = boardJson.getJSONObject(node);
                //图表中心预览，关联产品input节点没有field数组字段，需要解析fieldChecked构建formIdNodeIdMap, inputNodeIdSet参数，供handlerRelProduct方法使用
                if(Objects.equals(json.getString(XbbConstant.TYPE), DataSetNodeTypeEnum.INPUT.getAlias())) {
                    inputNodeIdSet.add(node);
                    Long formId = json.getLong(StringConstant.FORM_ID);
                    JSONArray fieldChecked = json.getJSONArray(XbbConstant.FIELD_CHECKED);
                    Integer businessType = json.getInteger(StringConstant.BUSINESS_TYPE);
                    BIProductReformEnum biProductReformEnum = BIProductReformEnum.getEnumByProductBusinessType(businessType);
                    if (Objects.nonNull(biProductReformEnum)) {
                        formIdNodeIdMap.put(formId,node);
                        List<ChartFieldAttrPojo> fieldAttrEntities = fieldChecked.stream().filter(fieldC -> fieldC.equals(SelectProductEnum.PRODUCT.getAttr())).map(field -> {
                            ChartFieldAttrPojo chartFieldAttrPojo = new ChartFieldAttrPojo();
                            chartFieldAttrPojo.setAttr(String.valueOf(field));
                            chartFieldAttrPojo.setBusinessType(businessType);
                            chartFieldAttrPojo.setFieldType(SelectProductEnum.PRODUCT.getFieldType());
                            chartFieldAttrPojo.setFormId(formId);
                            return chartFieldAttrPojo;
                        }).collect(Collectors.toList());
                        formIdMap.put(formId,new DataSetValueAnalysisPojo(json.getInteger(StringConstant.BUSINESS_TYPE),fieldAttrEntities));
                    }
                }else if(Objects.equals(json.getString(XbbConstant.TYPE), DataSetNodeTypeEnum.OUTPUT.getAlias())){
                    //输出节点直接去找他的input
                    nodeId  = json.getJSONArray(DataSetNodeTypeEnum.INPUT.getAlias()).getString(0);
                }
            }
        }
        JSONObject node = boardJson.getJSONObject(nodeId);
        boolean inputFlag = false; 
        if(Objects.equals(node.getString(XbbConstant.TYPE), DataSetNodeTypeEnum.INPUT.getAlias())){
            inputFlag = true;
        }
        JSONArray fieldArray = node.getJSONArray(XbbConstant.DS_FIELD);
        //关联产品特殊处理
        Map<Long,String> attrRelationProduct = Maps.newHashMap();
        //表头
        JSONArray  customTitle = new JSONArray();
        int size = fieldArray.size();
        Map<JSONObject, FieldAttrPojo> parseAttrMap = new HashMap<>(size);
        for (int i = 0; i < size; i++) {
            JSONObject jsonObject = fieldArray.getJSONObject(i);
            if(DataSetFieldStatusEnum.abnormalStatusList().contains(jsonObject.getInteger("status"))){
                continue;
            }
            if(inputFlag){
                String attr = jsonObject.getString(StringConstant.ATTR);
                //数据源节点没有映射，编号等驼峰字段的处理处理
                if (!attr.contains(XbbConstant.SEPARATOR)) {
                    attr = StringUtil.getDataBaseString(attr);
                }
                jsonObject.put(StringConstant.ATTR,attr);
            }else {
                if (formIdNodeIdMap.size()>0){
                    relatedProductHelper.handlerRelProduct(boardJson, formIdNodeIdMap, attrRelationProduct, jsonObject, inputNodeIdSet);
                }
            }
            ChartFieldAttrPojo fieldAttrPojo = JSONObject.parseObject(jsonObject.toJSONString(), ChartFieldAttrPojo.class);
            JSONObject headName = displayHelper.setHeadField(ChartTypeEnum.DATA_QUERY_TABLE.getCode(), fieldAttrPojo);
            if (FieldTypeEnum.isSubFormType(fieldAttrPojo.getFieldType())) {
                displayHelper.subFieldItems(fieldAttrPojo, headName);
            }
            customTitle.add(headName);
            parseAttrMap.put(headName, fieldAttrPojo);
        }
        JSONArray resultDataArray = JSONArray.parseArray(JSON.toJSONString(resultList));
        Set<Long> formIdKeySet = formIdMap.keySet();
        for (Long formId : formIdKeySet) {
            DataSetValueAnalysisPojo dataSetValueAnalysisPojo = formIdMap.get(formId);
            /*List<ChartFieldAttrPojo> fieldList = dataSetValueAnalysisPojo.getFieldList();
            Map<String,ChartFieldAttrPojo>  map = new HashMap(fieldList.size());
            for (ChartFieldAttrPojo fieldAttrPojo : fieldList) {
                map.put(fieldAttrPojo.getAttr(),fieldAttrPojo);
            }
            dataSetValueAnalysisPojo.setMap(map);
            formIdMap.put(formId,dataSetValueAnalysisPojo);*/
            String relProductAttr = attrRelationProduct.get(formId);
            if (attrRelationProduct.size()>0 || inputFlag){
                relatedProductHelper.getNewProduct(dataSetParseDTO.getCorpid(), customTitle, dataSetValueAnalysisPojo.getBusinessType(), resultDataArray,relProductAttr);
            }
        }
        JSONArray row = new JSONArray();
        JSONArray rowExplain = new JSONArray();
        List<List<String>> resultCol = new ArrayList<>();
        List<String> dataIdList = new ArrayList<>();
        for (int i = 0; i < customTitle.size(); i++) {
            ChartEntity chartEntity = new ChartEntity();
            dataQueryTableStrategyServiceImpl.parseData(dataSetParseDTO, chartEntity, customTitle, parseAttrMap, resultDataArray, row, rowExplain, resultCol, dataIdList, null, false, i,dataSetParseDTO.isInputPreView());
        }
        List<JSONObject> dataList = JSONObject.parseArray(row.toJSONString(), JSONObject.class);
        JSONArray queryTableResult = chartResultHelp.queryTableAssemble(resultCol, dataList, rowExplain);
        PageHelper pageHelper = new PageHelper(1,10);
        pageHelper.setPageTotal(resultList.size());
        dataSetResultVO.setResultList(queryTableResult);
        dataSetResultVO.setCustomTitle(customTitle);
        dataSetResultVO.setRealRowsCount(resultDataArray.size());
        dataSetResultVO.setPageHelper(pageHelper);
        return dataSetResultVO;
    }


    @Override
    public DataSetResultVO getResult(DataSetParseDTO dataSetParseDTO, String reqSource) throws XbbException {
        //图表新建页不传jsonStr，需要从数据库获取
        if(XbbConstant.REQ_SOURCE_CHART.equals(reqSource)){
            if(Objects.isNull(dataSetParseDTO.getDataSetId())){
                throw new XbbException(BiErrorCodeEnum.API_ERROR_241040);
            }
            DataSetEntity dataSetEntity = dataSetHelp.getDataSetEntity(dataSetParseDTO.getDataSetId(), dataSetParseDTO.getCorpid());
            JSONObject jsonStr = dataSetEntity.getBoard();
            dataSetParseDTO.setJsonStr(jsonStr);
        }
        return getResult(dataSetParseDTO);
    }
}
